﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using ESupervision.Models;
using ESupervision.Services;


namespace ESupervision.Controllers
{
    [Authorize]
    public class MessageController : Controller
    {
        private ApplicationDbContext db = new ApplicationDbContext();
        private readonly IMessageService messageService;

        public MessageController(IMessageService messageService)
        {
            this.messageService = messageService;
        }

        // GET: /Message/
        public async Task<ActionResult> Index()
        {
            // Get current User
           // ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.UserName == User.Identity.GetUserName());

            string userId = User.Identity.GetUserId();
          
            return View(await messageService.GetInboxMessages(db, userId));
        }

        public async Task<ActionResult> Sent()
        {
            // Get current User
            // ApplicationUser currentUser = db.Users.FirstOrDefault(x => x.UserName == User.Identity.GetUserName());

            string userId = User.Identity.GetUserId();   

            //var messages = db.Messages.Include(m => m.Sender);
            return View(await messageService.GetSentMessages(db, userId));
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> DoAction(int[] selectedMessages, int[] selectedSentMessages, string command)
        {
            if (ModelState.IsValid)
            {
                if (selectedMessages != null)
                {

                    if (command == "Delete")
                    {
                        foreach (var messageID in selectedMessages)
                        {
                            var message = await db.MessageRecipients.FindAsync(messageID);

                            if (message != null)
                            {
                                db.MessageRecipients.Remove(message);
                            }
                        }
                    }
                    else if (command == "Mark As Read")
                    {
                        foreach (var messageID in selectedMessages)
                        {
                            var message = await db.MessageRecipients.FindAsync(messageID);
                            if (message != null)
                            {
                                message.MessageStatus = MessageStatus.Read;

                            }
                        }
                    }
                    else if (command == "Mark As UnRead")
                    {
                        foreach (var messageID in selectedMessages)
                        {
                            var message = await db.MessageRecipients.FindAsync(messageID);
                            if (message != null)
                            {
                                message.MessageStatus = MessageStatus.Unread;

                            }
                        }

                    }
                    await db.SaveChangesAsync();
                    return RedirectToAction("Index");
                }
                else
                {
                    if (selectedSentMessages != null)
                    {

                        if (command == "Delete")
                        {
                            foreach (var messageID in selectedSentMessages)
                            {
                                var message = await db.MessageSents.FindAsync(messageID);

                                if (message != null)
                                {
                                    db.MessageSents.Remove(message);
                                }
                            }
                        }
                        else if (command == "Mark As Read")
                        {
                            foreach (var messageID in selectedSentMessages)
                            {
                                var message = await db.MessageSents.FindAsync(messageID);
                                if (message != null)
                                {
                                    message.MessageStatus = MessageStatus.Read;

                                }
                            }
                        }
                        else if (command == "Mark As UnRead")
                        {
                            foreach (var messageID in selectedSentMessages)
                            {
                                var message = await db.MessageSents.FindAsync(messageID);
                                if (message != null)
                                {
                                    message.MessageStatus = MessageStatus.Unread;

                                }
                            }

                        }
                        await db.SaveChangesAsync();
                        return RedirectToAction("Sent");
                    }
                }
            }

            return RedirectToAction("Index");
            
        }
        // GET: /Message/Details/5


        public async Task<ActionResult> Delete(int? id, int? rId, int? sId)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            

            if (rId != null)
            {
                await messageService.DeleteReceivedMessage(db, rId.GetValueOrDefault());
                return RedirectToAction("Index");
            }
            else
            {

                if (sId != null)
                {
                    await messageService.DeleteSentMessage(db, sId.GetValueOrDefault());
                    return RedirectToAction("Sent");
                }
            }
          
            
            Message message = await db.Messages.FindAsync(id);
            if (message == null)
            {
                return HttpNotFound();
            }
            ViewBag.Current = "Inbox";
            return View(message);
            
        }

        public async Task<ActionResult> Read(int? id, int? rId, int? sId)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Message message = await db.Messages.FindAsync(id);
            if (message == null)
            {
                return HttpNotFound();
            }

            if (rId != null)
            {
                MessageRecipient messageRecipient = await db.MessageRecipients.FindAsync(rId);
                if (messageRecipient != null)
                {
                    if (messageRecipient.MessageStatus != MessageStatus.Read)
                    {
                        messageRecipient.MessageStatus = MessageStatus.Read;
                        db.SaveChanges();
                    }
                }

                ViewBag.Current = "Inbox";
            }
            if (sId != null)
            {
                MessageSent messageSent = await db.MessageSents.FindAsync(sId);
                if (messageSent != null)
                {
                    if (messageSent.MessageStatus != MessageStatus.Read)
                    {
                        messageSent.MessageStatus = MessageStatus.Read;
                        db.SaveChanges();
                    }
                }
                ViewBag.Current = "Sent";
            }
            return View(message);
        }

        public ActionResult Reply(int? id, int? rId, int? sId)
        {
            if (id != null)
            {
                var message = db.Messages.Find(id);
                if (message != null)
                {
                    PopulateToUserData(message);
                    var replyMessage = new Message
                    {
                        SentByUserId = message.SentByUserId,
                        SentTime = DateTime.Now,
                        Subject = "Re: " + message.Subject
                    };
                    return View("Compose", replyMessage);
                }
            }
            string userId = User.Identity.GetUserId();
            PopulateToUserData(userId);
            var model = new Message
            {
                SentByUserId = userId,
                SentTime = DateTime.Now
            };
            return View("Compose", model);
           
        }
        // GET: /Message/Compose
        public ActionResult Compose()
        {
           
            string userId = User.Identity.GetUserId();
            PopulateToUserData(userId);
            var model = new Message
            {
                SentByUserId = userId,
                SentTime = DateTime.Now
            };
            return View(model);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Reply([Bind(Include = "ID,SentByUserId,Subject,Body")] Message message, string[] selectedUsers)
        {
            if (ModelState.IsValid)
            {
                if (selectedUsers != null)
                {
                    List<ApplicationUser> receivers = new List<ApplicationUser>();
                    foreach (var userId in selectedUsers)
                    {
                        ApplicationUser receiver = db.Users.Find(userId);
                        if (receiver != null)
                        {
                            receivers.Add(receiver);
                        }
                    }
                    message.SentByUserId = User.Identity.GetUserId();
                    message.SentTime = DateTime.Now;
                    await messageService.SendMessage(db, message, receivers);

                    return RedirectToAction("Index");
                }

            }


            PopulateToUserData(User.Identity.GetUserId());
            return View(message);
        }
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Compose([Bind(Include = "ID,SentByUserId,Subject,Body")] Message message, string[] selectedUsers)
        {
            if (ModelState.IsValid)
            {
                if(selectedUsers != null)
                {
                    List<ApplicationUser> receivers = new List<ApplicationUser>();
                    foreach (var userId in selectedUsers)
                    {
                        ApplicationUser receiver = db.Users.Find(userId);
                        if (receiver != null)
                        {
                            receivers.Add(receiver);
                        }
                    }
                    message.SentByUserId = User.Identity.GetUserId();
                    message.SentTime = DateTime.Now;
                    await messageService.SendMessage(db, message, receivers);

                    return RedirectToAction("Index");
                }
                
            }

            
            PopulateToUserData(User.Identity.GetUserId());
            return View(message);
        }

     
        private void PopulateToUserData(String userId)
        {
            if (User.IsInRole("Student"))
            {
                Student student = db.Students.Find(userId);
                PopulateToUserData(student);
            }
            else
            {
                if (User.IsInRole("Teacher"))
                {
                    Teacher staff = db.Teachers.Find(userId);
                    PopulateToUserData(staff);
                }
            }
        }
        private void PopulateToUserData(Message message)
        {
            var toUsers = new List<ApplicationUser>();
            if (message.MessageSents != null)
            {
                foreach (var messageSent in message.MessageSents)
                {
                    toUsers.Add(messageSent.SentUser);
                }
            }
            if (message.MessageRecipients != null)
            {
                foreach (var messageRecipient in message.MessageRecipients)
                {
                    toUsers.Add(messageRecipient.ReceiverUser);
                }
            }
            ViewBag.ToUsers = toUsers;
        }
        private void PopulateToUserData(Student student)
        {
            var toUsers = new List<ApplicationUser>();
            toUsers.Add(student.Supervisor);
            toUsers.Add(student.SecondMarker);
            ViewBag.ToUsers = toUsers;
            ViewBag.ToUsersSelectList = new SelectList(toUsers, "id", "FullName");//New Code for creating select list
        }

        private void PopulateToUserData(Teacher staff)
        {

            var toUsers = new List<ApplicationUser>();
            if(staff.SupervisedStudents != null)
                toUsers.AddRange(staff.SupervisedStudents);

            if (staff.SecondMarkedStudents != null)
                toUsers.AddRange(staff.SecondMarkedStudents);

            ViewBag.ToUsers = toUsers;
            ViewBag.ToUsersSelectList = new SelectList(toUsers, "id", "FullName");//New Code for creating select list
        }

        

        // GET: /Message/Edit/5
        public async Task<ActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Message message = await db.Messages.FindAsync(id);
            if (message == null)
            {
                return HttpNotFound();
            }
            ViewBag.SentByUserId = new SelectList(db.Students, "Id", "UserName", message.SentByUserId);
            return View(message);
        }

        // POST: /Message/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit([Bind(Include="ID,SentByUserId,Subject,Body,SentTime")] Message message)
        {
            if (ModelState.IsValid)
            {
                db.Entry(message).State = EntityState.Modified;
                await db.SaveChangesAsync();
                return RedirectToAction("Index");
            }
            ViewBag.SentByUserId = new SelectList(db.Students, "Id", "UserName", message.SentByUserId);
            return View(message);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}
